#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <pthread.h>
#include "sim_main_process.h"
#include "usim_process.h"
#include "common.h"
#include "sim_process.h"
#include <errno.h>

#include "p_lib.h"


Common_Data Data;
IMSI_Data	Para;
int			Fd;

const unsigned char ATR_READ[33] = {
	0x3B, 0x9C, 0x94, 0x80, 0x1F, 0x47, 0x80, 0x31, 0xE0, 0x73, 0xFE, 0x21, 0x1B, 0x54, 0x53, 0x04, 0x71, 0x6B, 0x2F
};

unsigned char IMSI[IMSI_LEN] = {
	0x80, 0x94, 0x60, 0x06,
	0x00, 0x49, 0x03, 0x03, 0x20
};//for test


static Sim_Type_enum usim_process_ATR(unsigned char *ATR)
{
	unsigned char  data;
	unsigned char *ptr = NULL;
	int index = 1;	// skip the first TS byte
	Sim_Type_enum retval = UNKNOWN;
	ptr = ATR;

	if((0x3B != ATR[0])&&(0X3F != ATR[0])) 
		return retval;

	if((ptr[index] & 0x0f) == 0)
		retval = SIM; 

	do
	{
		data = ptr[index++];
		USIM_CAL_TD_COUNT(data, index);
	}while(data & TDMask);

	if(ptr[index] == HIST_FIRST_USIM && ptr[index + 1] == HIST_SEC_USIM)
		retval = USIM;
	else
		retval= SIM;

	return retval;
}

static void VUSIM_SFI_init()
{
    memset(USIM_ADF_EF_SFI_LIST, 0xFF, (MAX_ADF_EF_SFI_LIST * (sizeof(SFI_LIST))));
    USIM_ADF_EF_SFI_Num = (sizeof(USIM_ADF_EF_SFI_DEFAULT_LIST)/(sizeof(SFI_LIST)));
    DBUG( "VUSIM_init:ADF_EF SFI LIST initial Num = %d\n", USIM_ADF_EF_SFI_Num);
    memcpy(USIM_ADF_EF_SFI_LIST, USIM_ADF_EF_SFI_DEFAULT_LIST, sizeof(USIM_ADF_EF_SFI_DEFAULT_LIST));

    return;
}

void VUSIM_init(void)
{
	Data.USAT_SW1 = 0x90;
	Data.VUSIM_Global.VsimType = usim_process_ATR(Data.DEFAULT_ATR);

	if(USIM == Data.VUSIM_Global.VsimType)
		VUSIM_SFI_init();
	else
		memset(VSIM_Auth, 0, (VSIM_AUTH_RECORD_MAX * sizeof(VSIM_Auth_t)));

	DBUG( "The VsimType is %d\n", Data.VUSIM_Global.VsimType);

	return;	
}

int VUSIM_ATR(void)
{
	VUSIM_RetData(Data.DEFAULT_ATR, Data.ATR_Len);
    //Sim_Log_Hex("ATR=", Data.DEFAULT_ATR, Data.ATR_Len);

    //add for 91 A5 can be changed
    if(Data.FCH_Size > 0)
    {
        Data.USAT_SW1 = 0x91;
        Data.USAT_SW2 = Data.FCH_Size;
    }

    return 0;
}

void TT_Recv_Set(unsigned char *Dat, unsigned char DatLen, unsigned char RcvCnt)
{
    TT_Ctl_t *p_ctl = &Data.g_TT_ctl;
    int i =0;
    struct timeval cur_time;
    gettimeofday(&cur_time, NULL);

    if((Dat == NULL )||(DatLen == 0)) return ;

	switch(Data.VUSIM_Global.VsimType)
	{
		case USIM:
        	if(RcvCnt != p_ctl->Snd_Cnt)
        	{
        	    DBUG( "snd cnt =%d recv cnt=%d\n", p_ctl->Snd_Cnt, RcvCnt);
        	    return;
        	}
        	memcpy(p_ctl->RcvBuf, Dat, DatLen);
        	memcpy(&(p_ctl->rcv_time), &cur_time, sizeof(cur_time));
        	p_ctl->Rcv_Len = DatLen;
        	p_ctl->flag = TRANSFER_TRANSPARENT_OVER ;
			break;
		case SIM:
			for(i = 0; i < VSIM_AUTH_RECORD_MAX; i++)
			{
				if(RcvCnt == VSIM_Auth[i].cnt)
				{
					DBUG( "[TT_Recv_Set]data of cnt%d recved, the num is %d, flag is %d\n", VSIM_Auth[i].cnt, i, VSIM_Auth[i].flag);
					memcpy(VSIM_Auth[i].AuthResult, Dat, DatLen);
					VSIM_Auth[i].AuthResult_Len = DatLen;
					//Debuf_Print_Data(VSIM_Auth[i].AuthResult, VSIM_Auth[i].AuthResult_Len, "[TT_Recv_Set]Recv data is ");
					VSIM_Auth[i].flag = TT_Recved;
					memcpy(&(VSIM_Auth[i].rcv_time), &cur_time, sizeof(cur_time));
					DBUG("[TT_Recv_Set]VSIM time1 spend on socket is %ld ms\n",
							(VSIM_Auth[i].rcv_time.tv_sec - VSIM_Auth[i].snd_time.tv_sec)*1000+(VSIM_Auth[i].rcv_time.tv_usec - VSIM_Auth[i].snd_time.tv_usec)/1000);
				}
			}
			break;
		default:
			break;
    }

    return;
}

void VisulSimProccess(unsigned char *recvBuf, int iRecvLen)
{
	if((iRecvLen <= 0)||(recvBuf == NULL))
	{
		DBUG("[VisulSimProccess]Para error\n");
		return;
	}

	switch(Data.VUSIM_Global.VsimType)
	{
		case USIM:
			VUSIM_MAIN_PROC(recvBuf, iRecvLen, 0);
			break;
		case SIM:
			VSIM_MAIN_PROC(recvBuf, iRecvLen);
			break;
		default:
			break;
	}

	return;
}


void SetTT_Snd_Sta(int Snd_cnt, int state)
{
	int i = 0;

	if(Data.VUSIM_Global.VsimType == SIM)
	{
		for(i = 0; i < VSIM_AUTH_RECORD_MAX; i++)
		{
			if( Snd_cnt == VSIM_Auth[i].cnt)
			{
				VSIM_Auth[i].flag = state;
				break;
			}
		}
	}	

	return;
}

int GetVisualSIM_TT_Data(unsigned char *TTbuf, unsigned char *Snd_cnt)
{
	TT_Ctl_t * p_ctl = &Data.g_TT_ctl ;
	if(TTbuf == NULL ) return 0;
	memcpy(TTbuf, p_ctl->SndBuf, p_ctl->Snd_Len);
	*Snd_cnt = p_ctl->Snd_Cnt ;

	return p_ctl->Snd_Len;
}

int Set_IMSI_Para(unsigned char *IMSI, TT_Data *para)
{
	if(NULL == IMSI || NULL == para)
	{
		DBUG( "%s para err\n", __func__);
		return -1;
	}

	if(!memcmp(Para.IMSI, IMSI, IMSI_LEN))
		return 0;

	memcpy(Para.IMSI, IMSI, IMSI_LEN);
	Hex2String(IMSI, Para.sIMSI, IMSI_LEN);
	memcpy(&Para.Spm_Para, para, sizeof(TT_Data));
	DBUG("the ip is %d.%d.%d.%d\n", Para.Spm_Para.IP[0], Para.Spm_Para.IP[1], Para.Spm_Para.IP[2], Para.Spm_Para.IP[3]);

	return 0;
}


void *ISO7816_ANL_StaMacine(void *arg)
{

	//VUSIM_init(dev_fd);

	VUSIM_ATR();
	
	//VisulSimProccess(RecvBuf, iRecvLen);
}

